using System.Text.Json;
using WeatherSystem.API.Data;
using WeatherSystem.API.Models;
using Microsoft.EntityFrameworkCore;
using WeatherSystem.API.Helpers;
using WeatherSystem.API.Configurations;

namespace WeatherSystem.API.Services
{
    /// <summary>
    /// 天气数据服务接口
    /// </summary>
    public interface IWeatherService
    {
        Task<WeatherDataEntry?> GetLatestWeatherAsync(Guid cityId);
        Task<List<WeatherDataEntry>> GetWeatherHistoryAsync(Guid cityId, DateTime startDate, DateTime endDate);
        Task<WeatherDataEntry> CollectWeatherDataAsync(Guid cityId);
        Task GenerateDailyStatisticsAsync();
        Task<Dictionary<string, object>> GetWeatherDataAsDictionaryAsync(Guid entryId);
        Task<List<Dictionary<string, object>>> GetWeatherHistoryAsDictionaryAsync(Guid cityId, DateTime startDate, DateTime endDate);
        Task<List<Guid>> CreateWeatherDataBatchAsync(List<CreateDynamicWeatherDataRequest> requests);
        Task<bool> UpdateWeatherDataAsync(Guid id, UpdateDynamicWeatherDataRequest request);
        Task<bool> DeleteWeatherDataAsync(Guid id);
    }

    /// <summary>
    /// 天气数据服务实现
    /// </summary>
    public class WeatherService : IWeatherService
    {
        private readonly WeatherDbContext _context;
        private readonly IWeatherApiService _weatherApiService;
        private readonly ILogger<WeatherService> _logger;
        private readonly IMetricConfigurationService _metricConfigurationService;
        private readonly ICacheService _cacheService;
        private readonly IBusinessMetricsService _metricsService;

        public WeatherService(
            WeatherDbContext context,
            IWeatherApiService weatherApiService,
            ILogger<WeatherService> logger,
            IMetricConfigurationService metricConfigurationService,
            ICacheService cacheService,
            IBusinessMetricsService metricsService)
        {
            _context = context;
            _weatherApiService = weatherApiService;
            _logger = logger;
            _metricConfigurationService = metricConfigurationService;
            _cacheService = cacheService;
            _metricsService = metricsService;
        }

        /// <summary>
        /// 获取最新天气数据
        /// </summary>
        public async Task<WeatherDataEntry?> GetLatestWeatherAsync(Guid cityId)
        {
            try
            {
                var cacheKey = $"weather:latest:{cityId}";
                
                return await _cacheService.GetOrSetAsync(cacheKey, async () =>
                {
                    return await _context.WeatherDataEntries
                        .Include(e => e.City)
                        .Include(e => e.Metrics.Where(m => m.Definition != null && m.Definition.IsActive))
                        .ThenInclude(m => m.Definition)
                        .Where(e => e.CityId == cityId)
                        .OrderByDescending(e => e.RecordedAt)
                        .FirstOrDefaultAsync();
                }, TimeSpan.FromMinutes(5));
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取最新天气数据失败，城市ID: {CityId}", cityId);
                throw;
            }
        }

        /// <summary>
        /// 获取历史天气数据
        /// </summary>
        public async Task<List<WeatherDataEntry>> GetWeatherHistoryAsync(Guid cityId, DateTime startDate, DateTime endDate)
        {
            try
            {
                var cacheKey = $"weather:history:{cityId}:{startDate:yyyyMMdd}:{endDate:yyyyMMdd}";
                
                return await _cacheService.GetOrSetAsync(cacheKey, async () =>
                {
                    return await _context.WeatherDataEntries
                        .Include(e => e.City)
                        .Include(e => e.Metrics.Where(m => m.Definition != null && m.Definition.IsActive))
                        .ThenInclude(m => m.Definition)
                        .Where(e => e.CityId == cityId && 
                                   e.RecordedAt >= startDate && 
                                   e.RecordedAt <= endDate)
                        .OrderBy(e => e.RecordedAt)
                        .AsNoTracking()
                        .ToListAsync();
                }, TimeSpan.FromMinutes(10));
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取历史天气数据失败，城市ID: {CityId}, 开始时间: {StartDate}, 结束时间: {EndDate}", 
                    cityId, startDate, endDate);
                throw;
            }
        }

        /// <summary>
        /// 采集天气数据
        /// </summary>
        public async Task<WeatherDataEntry> CollectWeatherDataAsync(Guid cityId)
        {
            var startTime = DateTime.UtcNow;
            DataCollectionLog log = new()
            {
                CityId = cityId,
                ExecutionTime = startTime
            };

            try
            {
                // 获取城市信息
                var city = await _context.Cities.FindAsync(cityId);
                if (city == null)
                {
                    throw new ArgumentException($"城市不存在: {cityId}");
                }

                // 调用天气API获取数据
                var apiData = await _weatherApiService.GetCurrentWeatherAsync(city.Latitude, city.Longitude);
                
                // 转换为EAV数据模型
                var weatherDataEntry = new WeatherDataEntry
                {
                    CityId = cityId,
                    RecordedAt = DateTime.UtcNow,
                    Source = "WeatherAPI"
                };

                // 处理动态指标：根据城市配置创建MetricValue记录
                var metricValues = new List<MetricValue>();
                try
                {
                    var enabledMetrics = await _context.MetricDefinitions
                        .Where(m => m.IsActive)
                        .ToListAsync();
                        
                    foreach (var def in enabledMetrics)
                    {
                        object? value = null;
                        switch (def.Key)
                        {
                            case "temperature": value = apiData.Temperature; break;
                            case "humidity": value = apiData.Humidity; break;
                            case "pressure": value = apiData.Pressure; break;
                            case "windSpeed": value = apiData.WindSpeed; break;
                            case "windDirection": value = apiData.WindDirection; break;
                            case "visibility": value = apiData.Visibility; break;
                            case "uvIndex": value = apiData.UVIndex; break;
                            case "weatherCondition": value = apiData.WeatherCondition; break;
                        }

                        if (value != null)
                        {
                            metricValues.Add(new MetricValue
                            {
                                WeatherDataEntryId = weatherDataEntry.Id,
                                MetricKey = def.Key,
                                RawValue = value.ToString()!,
                                DataType = def.DataType
                            });
                        }
                    }
                }
                catch (Exception ex)
                {
                    _logger.LogWarning(ex, "创建动态指标失败，城市ID: {CityId}", cityId);
                }

                weatherDataEntry.Metrics = metricValues;

                // 保存到数据库
                _context.WeatherDataEntries.Add(weatherDataEntry);
                await _context.SaveChangesAsync();

                // 清除相关缓存
                await InvalidateWeatherCacheAsync(cityId);

                // 记录成功日志
                log.Status = "Success";
                log.RecordsCollected = 1;
                log.Message = "数据采集成功";
                
                // 记录业务指标
                _metricsService.RecordWeatherDataCollected(cityId.ToString(), "WeatherAPI");
                
                var tempMetric = metricValues.FirstOrDefault(m => m.MetricKey == "temperature");
                var tempValue = tempMetric?.RawValue ?? "N/A";
                _logger.LogInformation("天气数据采集成功，城市: {CityName}, 温度: {Temperature}°C", 
                    city.Name, tempValue);

                return weatherDataEntry;
            }
            catch (Exception ex)
            {
                log.Status = "Failed";
                log.Message = ex.Message;
                
                _logger.LogError(ex, "天气数据采集失败，城市ID: {CityId}", cityId);
                throw;
            }
            finally
            {
                log.Duration = (int)(DateTime.UtcNow - startTime).TotalMilliseconds;
                _context.DataCollectionLogs.Add(log);
                await _context.SaveChangesAsync();
            }
        }


        /// <summary>
        /// 生成每日统计数据（使用动态统计服务）
        /// </summary>
        public async Task GenerateDailyStatisticsAsync()
        {
            try
            {
                var yesterday = DateTime.Today.AddDays(-1);
                
                // 调用统计服务的生成方法
                var statisticsService = new StatisticsService(_context, _logger as ILogger<StatisticsService> ?? throw new InvalidOperationException("Logger not available"), _metricConfigurationService);
                await statisticsService.GenerateDailyStatisticsAsync(yesterday);

                _logger.LogInformation("每日统计数据生成完成，日期: {Date}", yesterday);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "生成每日统计数据失败");
                throw;
            }
        }


        /// <summary>
        /// 获取天气数据的字典表示
        /// </summary>
        public async Task<Dictionary<string, object>> GetWeatherDataAsDictionaryAsync(Guid entryId)
        {
            var entry = await _context.WeatherDataEntries
                .Include(e => e.Metrics)
                .ThenInclude(m => m.Definition)
                .FirstOrDefaultAsync(e => e.Id == entryId);

            if (entry == null)
                return new Dictionary<string, object>();

            var result = new Dictionary<string, object>
            {
                ["id"] = entry.Id,
                ["cityId"] = entry.CityId,
                ["recordedAt"] = entry.RecordedAt,
                ["source"] = entry.Source ?? string.Empty
            };

            foreach (var metric in entry.Metrics)
            {
                result[metric.MetricKey] = ConvertRawValueToTyped(metric.RawValue, metric.DataType);
            }

            return result;
        }

        /// <summary>
        /// 获取历史天气数据的字典列表
        /// </summary>
        public async Task<List<Dictionary<string, object>>> GetWeatherHistoryAsDictionaryAsync(Guid cityId, DateTime startDate, DateTime endDate)
        {
            var entries = await GetWeatherHistoryAsync(cityId, startDate, endDate);
            var result = new List<Dictionary<string, object>>();

            foreach (var entry in entries)
            {
                var dict = new Dictionary<string, object>
                {
                    ["id"] = entry.Id,
                    ["cityId"] = entry.CityId,
                    ["recordedAt"] = entry.RecordedAt,
                    ["source"] = entry.Source ?? string.Empty
                };

                foreach (var metric in entry.Metrics)
                {
                    dict[metric.MetricKey] = ConvertRawValueToTyped(metric.RawValue, metric.DataType);
                }

                result.Add(dict);
            }

            return result;
        }

        /// <summary>
        /// 从EAV数据中提取指定指标的数值
        /// </summary>
        private List<decimal> GetMetricValues(List<WeatherDataEntry> entries, string metricKey)
        {
            var values = new List<decimal>();
            
            foreach (var entry in entries)
            {
                var metric = entry.Metrics.FirstOrDefault(m => m.MetricKey == metricKey);
                if (metric != null && decimal.TryParse(metric.RawValue, out var value))
                {
                    values.Add(value);
                }
            }

            return values;
        }

        /// <summary>
        /// 计算EAV数据的扩展统计信息
        /// </summary>
        private Dictionary<string, object> CalculateExtendedStatisticsFromEAV(List<WeatherDataEntry> entries)
        {
            var result = new Dictionary<string, object>();

            // 获取所有指标类型
            var allMetricKeys = entries
                .SelectMany(e => e.Metrics)
                .Select(m => m.MetricKey)
                .Distinct()
                .ToList();

            foreach (var metricKey in allMetricKeys)
            {
                var values = GetMetricValues(entries, metricKey);
                if (values.Any())
                {
                    result[$"avg{MetricsHelper.ToPascalCase(metricKey)}"] = Math.Round(values.Average(), 2);
                    result[$"max{MetricsHelper.ToPascalCase(metricKey)}"] = values.Max();
                    result[$"min{MetricsHelper.ToPascalCase(metricKey)}"] = values.Min();
                }
            }

            return result;
        }

        /// <summary>
        /// 将原始值转换为相应的类型
        /// </summary>
        private object ConvertRawValueToTyped(string rawValue, string dataType)
        {
            return dataType.ToLower() switch
            {
                "decimal" => decimal.TryParse(rawValue, out var d) ? d : 0m,
                "int" => int.TryParse(rawValue, out var i) ? i : 0,
                "boolean" => bool.TryParse(rawValue, out var b) && b,
                _ => rawValue
            };
        }

        /// <summary>
        /// 使相关天气数据缓存失效
        /// </summary>
        private async Task InvalidateWeatherCacheAsync(Guid cityId)
        {
            try
            {
                await _cacheService.RemoveAsync($"weather:latest:{cityId}");
                await _cacheService.RemovePatternAsync($"weather:history:{cityId}:*");
                await _cacheService.RemovePatternAsync($"weather:statistics:{cityId}:*");
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "缓存失效操作失败，城市ID: {CityId}", cityId);
            }
        }

        /// <summary>
        /// 批量创建天气数据
        /// </summary>
        public async Task<List<Guid>> CreateWeatherDataBatchAsync(List<CreateDynamicWeatherDataRequest> requests)
        {
            var results = new List<Guid>();
            
            foreach (var request in requests)
            {
                var weatherDataEntry = new WeatherDataEntry
                {
                    CityId = request.CityId,
                    RecordedAt = request.RecordedAt,
                    Source = request.Source ?? "Batch"
                };

                var metricValues = new List<MetricValue>();
                if (request.Metrics != null)
                {
                    var validMetrics = await _context.MetricDefinitions
                        .Where(m => m.IsActive)
                        .ToListAsync();

                    foreach (var kvp in request.Metrics)
                    {
                        var metricDef = validMetrics.FirstOrDefault(m => m.Key == kvp.Key);
                        if (metricDef != null)
                        {
                            metricValues.Add(new MetricValue
                            {
                                WeatherDataEntryId = weatherDataEntry.Id,
                                MetricKey = kvp.Key,
                                RawValue = kvp.Value?.ToString() ?? string.Empty,
                                DataType = metricDef.DataType
                            });
                        }
                    }
                }

                weatherDataEntry.Metrics = metricValues;
                _context.WeatherDataEntries.Add(weatherDataEntry);
                results.Add(weatherDataEntry.Id);
            }

            await _context.SaveChangesAsync();
            return results;
        }

        /// <summary>
        /// 更新天气数据
        /// </summary>
        public async Task<bool> UpdateWeatherDataAsync(Guid id, UpdateDynamicWeatherDataRequest request)
        {
            var entry = await _context.WeatherDataEntries
                .Include(e => e.Metrics)
                .FirstOrDefaultAsync(e => e.Id == id);

            if (entry == null)
            {
                return false;
            }

            // 更新基本信息
            if (request.CityId.HasValue)
                entry.CityId = request.CityId.Value;
            if (request.RecordedAt.HasValue)
                entry.RecordedAt = request.RecordedAt.Value;
            if (!string.IsNullOrEmpty(request.Source))
                entry.Source = request.Source;

            // 更新指标值
            if (request.Metrics != null)
            {
                var validMetrics = await _context.MetricDefinitions
                    .Where(m => m.IsActive)
                    .ToListAsync();

                foreach (var kvp in request.Metrics)
                {
                    var existingMetric = entry.Metrics.FirstOrDefault(m => m.MetricKey == kvp.Key);
                    var metricDef = validMetrics.FirstOrDefault(m => m.Key == kvp.Key);

                    if (metricDef != null)
                    {
                        if (existingMetric != null)
                        {
                            existingMetric.RawValue = kvp.Value?.ToString() ?? string.Empty;
                            existingMetric.DataType = metricDef.DataType;
                        }
                        else
                        {
                            entry.Metrics.Add(new MetricValue
                            {
                                WeatherDataEntryId = entry.Id,
                                MetricKey = kvp.Key,
                                RawValue = kvp.Value?.ToString() ?? string.Empty,
                                DataType = metricDef.DataType
                            });
                        }
                    }
                }
            }

            await _context.SaveChangesAsync();

            // 清除相关缓存
            await InvalidateWeatherCacheAsync(entry.CityId);

            return true;
        }

        /// <summary>
        /// 删除天气数据
        /// </summary>
        public async Task<bool> DeleteWeatherDataAsync(Guid id)
        {
            var entry = await _context.WeatherDataEntries
                .Include(e => e.Metrics)
                .FirstOrDefaultAsync(e => e.Id == id);

            if (entry == null)
            {
                return false;
            }

            _context.WeatherDataEntries.Remove(entry);
            await _context.SaveChangesAsync();

            // 清除相关缓存
            await InvalidateWeatherCacheAsync(entry.CityId);

            return true;
        }
    }

    /// <summary>
    /// 天气API响应数据模型
    /// </summary>
    public class WeatherApiResponse
    {
        public decimal Temperature { get; set; }
        public decimal Humidity { get; set; }
        public decimal Pressure { get; set; }
        public decimal WindSpeed { get; set; }
        public decimal? WindDirection { get; set; }
        public decimal? Visibility { get; set; }
        public decimal? UVIndex { get; set; }
        public string? WeatherCondition { get; set; }
    }
}